package com.atguigu.paymentdemo.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import javassist.compiler.ast.Variable;
import lombok.Data;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

/**
 * @author longge
 * @Title:
 * @Description:
 * @date 2023/2/5 12:07
 */
@Configuration
@PropertySource("classpath:wxpay.properties")
@ConfigurationProperties(prefix = "wxpay")
@Data
public class WxPayConfig implements Serializable {

    /**
     * 商户号
     */
    private String mchId;

    /**
     * 商户API证书序列号
     */
    private String mchSerialNo;

    /**
     * 商户私钥文件
     */
    private String privateKeyPath;

    /**
     * APIv3密钥
     */
    private String apiV3Key;

    /**
     * APPID
     */
    private String appid;

    /**
     * 微信服务器地址
     */
    private String domain;

    /**
     * 接收结果通知地址
     */
    private String notifyDomain;

    /**
     * @Description: 获取私钥
     * @return 私钥
     */
    public PrivateKey getPrivateKey() {
        PrivateKey privateKey =null;
        try {
            File file = ResourceUtils.getFile("classpath:" + this.getPrivateKeyPath());
            privateKey = PemUtil.loadPrivateKey(Files.newInputStream(file.toPath()));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("私钥文件找不到");
        }
        return privateKey;
    }

    /**
     * @Description: 获取签名验证器
     * @return verifier
     */
    @Bean
    public Verifier getVerifier(){
        Verifier verifier = null;

        try {
            //获取私钥
            PrivateKey privateKey = this.getPrivateKey();

            //获取私钥签名对象
            PrivateKeySigner privateKeySigner = new PrivateKeySigner(this.getMchSerialNo(), privateKey);

            //身份认证对象
            WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(this.getMchId(), privateKeySigner);

            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(this.getMchId(), wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));
            // ... 若有多个商户号，可继续调用putMerchant添加商户信息

            // 从证书管理器中获取verifier
            verifier = certificatesManager.getVerifier(this.getMchId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取签名验证器失败");
        }
        return verifier;
    }

    @Bean(name = "wxPayClient")
    public CloseableHttpClient getWxPayClient(){
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(this.getMchId(), this.getMchSerialNo(), this.getPrivateKey())
                .withValidator(new WechatPay2Validator(getVerifier()));
// ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

// 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        return builder.build();
    }

    /**
     * 获取HttpClient，无需进行应答签名验证，跳过验签的流程
     */
    @Bean(name = "wxPayNoSignClient")
    public CloseableHttpClient getWxPayNoSignClient(){

        //获取商户私钥
        PrivateKey privateKey = getPrivateKey();

        //用于构造HttpClient
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                //设置商户信息
                .withMerchant(this.getMchId(), this.getMchSerialNo(), privateKey)
                //无需进行签名验证、通过withValidator((response) -> true)实现
                .withValidator((response) -> true);

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新

        return builder.build();
    }
}
